#include "BasicBlock.h"
#include <algorithm>
#include "Function.h"

extern FILE* yyout;

// insert the instruction to the front of the basicblock.
void BasicBlock::insertFront(Instruction* inst) {
    insertBefore(inst, head->getNext());
}

// insert the instruction to the back of the basicblock.
void BasicBlock::insertBack(Instruction* inst) {
    insertBefore(inst, head);
}

// insert the instruction dst before src.
void BasicBlock::insertBefore(Instruction* dst, Instruction* src) {
    src->getPrev()->setNext(dst);
    dst->setPrev(src->getPrev());
    dst->setNext(src);
    src->setPrev(dst);

    dst->setParent(this);  // 设置这个新插入的指令的parent为当前基本块，类似于func与bb的关系
}

// remove the instruction from intruction list.
void BasicBlock::remove(Instruction* inst) {
    inst->getPrev()->setNext(inst->getNext());  // 前一个指针的后向节点
    inst->getNext()->setPrev(inst->getPrev());
}

void BasicBlock::output() const {
    fprintf(yyout, "B%d:", no);

    // 打印前继基本块
    if (!pred.empty()) {
        fprintf(yyout, "%*c; preds = %%B%d", 32, '\t', pred[0]->getNo());
        for (auto i = pred.begin() + 1; i != pred.end(); i++) {
            fprintf(yyout, ", %%B%d", (*i)->getNo());
        }
    }
    fprintf(yyout, "\n");

    // 打印所有的指令
    for (auto i = head->getNext(); i != head; i = i->getNext())
        i->output();
}

void BasicBlock::addSucc(BasicBlock* bb) {
    succ.push_back(bb);
}

// remove the successor basicclock bb.
void BasicBlock::removeSucc(BasicBlock* bb) {
    succ.erase(std::find(succ.begin(), succ.end(), bb));
}

void BasicBlock::addPred(BasicBlock* bb) {
    pred.push_back(bb);
}

// remove the predecessor basicblock bb.
void BasicBlock::removePred(BasicBlock* bb) {
    pred.erase(std::find(pred.begin(), pred.end(), bb));
}
void BasicBlock::genMachineCode(AsmBuilder* builder) {
    auto cur_func = builder->getFunction();
    auto cur_block = new MachineBlock(cur_func, no);
    builder->setBlock(cur_block);
    for (auto i = head->getNext(); i != head; i = i->getNext())
    {
        i->genMachineCode(builder);
    }
    cur_func->InsertBlock(cur_block);
}

BasicBlock::BasicBlock(Function *f) {
    this->no = SymbolTable::getLabel();  // return counter++ counter初始化为0
    f->insertBlock(this);  // func中的block list插入push back
    parent = f;
    head = new DummyInstruction();  // 头部初始指令，双向链表头，啥都不干
    head->setParent(this);
}

BasicBlock::~BasicBlock() {
    Instruction *inst;
    inst = head->getNext();
    while (inst != head) {
        Instruction *t;
        t = inst;
        inst = inst->getNext();
        delete t;
    }
    for (auto &bb:pred) {
        bb->removeSucc(this);
    }
    for (auto &bb:succ) {
        bb->removePred(this);
    }
    parent->remove(this);  // func中删除这个bb
}
